/*
 * By BEST PLM Team.
 *
 * Author: quhy1
 * Date: 2014-11-17
 */
package com.webridge.plm.util;

import java.beans.PropertyVetoException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

import wt.content.ApplicationData;
import wt.content.ContentHelper;
import wt.content.ContentHolder;
import wt.content.ContentItem;
import wt.content.ContentRoleType;
import wt.content.ContentServerHelper;
import wt.content.FormatContentHolder;
import wt.doc.WTDocument;
import wt.doc.WTDocumentMaster;
import wt.doc.WTDocumentMasterIdentity;
import wt.epm.EPMDocument;
import wt.epm.EPMDocumentMaster;
import wt.epm.EPMDocumentMasterIdentity;
import wt.fc.IdentityHelper;
import wt.fc.ObjectVector;
import wt.fc.ObjectVectorIfc;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.WTObject;
import wt.folder.Folder;
import wt.folder.FolderEntry;
import wt.folder.FolderHelper;
import wt.inf.container.WTContainer;
import wt.inf.container.WTContainerRef;
import wt.log4j.LogR;
import wt.method.RemoteAccess;
import wt.method.RemoteMethodServer;
import wt.org.WTPrincipal;
import wt.pds.StatementSpec;
import wt.query.ClassAttribute;
import wt.query.ConstantExpression;
import wt.query.OrderBy;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.query.TableColumn;
import wt.query.WhereExpression;
import wt.session.SessionHelper;
import wt.team.TeamReference;
import wt.type.TypeDefinitionReference;
import wt.type.TypedUtility;
import wt.util.WTAttributeNameIfc;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;
import wt.vc.VersionControlHelper;
import wt.vc.config.LatestConfigSpec;

import com.ptc.core.foundation.type.server.impl.TypeHelper;
import com.ptc.core.meta.common.TypeIdentifier;
import com.ptc.core.meta.type.mgmt.server.impl.WTTypeDefinition;
import com.ptc.core.meta.type.mgmt.server.impl.WTTypeDefinitionMaster;

public class DocUtil implements RemoteAccess {
    private final static Logger LOGGER = LogR
            .getLogger(DocUtil.class.getName());

    /**
     * getLatestDocumentByNumber
     * 
     * @param number
     * @return
     * @throws WTException
     */
    public static WTDocument getDocumentByNumber(String number)
            throws WTException {
        if (StringUtil.isEmpty(number)) {
            LOGGER.error(" number is null getDocumentByNumber");
            return null;
        }
        return getDocument(number, null, null);
    }

    /**
     * Get Document by nummber and state
     * 
     * @param number
     * @param state
     * @return
     * @throws WTException
     */
    public static WTDocument getDocumentByNumberAndState(String number,
            String state) throws WTException {
        if (StringUtil.isEmpty(number)) {
            LOGGER.error(" number is null getDocumentByNumberAndState");
            return null;
        }
        return getDocument(number, null, state);
    }

    /**
     * get latest WTDocument by name
     * 
     * @param name
     *            document name
     * @return WTDocument
     * @throws WTException
     */
    public static WTDocument getDocumentByName(String name) throws WTException {
        if (StringUtil.isEmpty(name)) {
            LOGGER.error(" name is null  getDocumentByName");
            return null;
        }
        LOGGER.debug("param doc name is " + name);
        return getDocument(null, name, null);
    }

    /**
     * Get Document by nummber and state
     * 
     * @param number
     * @param state
     * @return
     * @throws WTException
     */
    public static WTDocument getDocument(String number, String name,
            String state) throws WTException {
        WTDocument doc = null;
        QuerySpec querySpec = new QuerySpec(WTDocument.class);

        int conditionCount = 0;
        if (!StringUtil.isEmpty(number)) {
            SearchCondition searchCondi = new SearchCondition(WTDocument.class,
                    WTDocument.NUMBER, SearchCondition.EQUAL, number);
            querySpec.appendWhere(searchCondi, new int[] { 0 });
            conditionCount++;
        }

        if (!StringUtil.isEmpty(name)) {
            if (conditionCount > 0) {
                querySpec.appendAnd();
            }
            SearchCondition searchCondi = new SearchCondition(WTDocument.class,
                    WTDocument.NAME, SearchCondition.EQUAL, name);
            querySpec.appendWhere(searchCondi, new int[] { 0 });
            conditionCount++;
        }

        if (!StringUtil.isEmpty(state)) {
            if (conditionCount > 0)
            {
                querySpec.appendAnd();
            }
            SearchCondition searchCondi = new SearchCondition(WTDocument.class,
                    WTDocument.LIFE_CYCLE_STATE, SearchCondition.EQUAL, state);
            querySpec.appendWhere(searchCondi, new int[] { 0 });
        }
        QueryResult qr = PersistenceHelper.manager.find((StatementSpec) querySpec);
        qr = new LatestConfigSpec().process(qr);
        if (qr.hasMoreElements()) {
            doc = (WTDocument) qr.nextElement();
        }
        return doc;
    }

    /**
     * @param WTDocument
     * @return ApplicationData
     * @throws Exception
     * @throws WTException
     * @description get ApplicationData by WTDocument
     */
    public static ApplicationData getPrimaryContent(WTDocument document)
            throws WTException {
        ContentHolder contentHolder = null;
        ApplicationData applicationdata = null;
        try {
            LOGGER.debug("get content of : " + document.getNumber());
            contentHolder = ContentHelper.service
                    .getContents((ContentHolder) document);
            LOGGER.debug("contentHolder : " + contentHolder);
            ContentItem contentitem = ContentHelper
                    .getPrimary((FormatContentHolder) contentHolder);
            LOGGER.debug("primary : " + contentitem);
            applicationdata = (ApplicationData) contentitem;
        } catch (WTException e) {
            LOGGER.error(DocUtil.class + ".getPrimaryContent():", e);
            throw new WTException(e, e.getLocalizedMessage());
        } catch (Exception e) {
            LOGGER.error(DocUtil.class + ".getPrimaryContent():", e);
            throw new WTException(e, e.getLocalizedMessage());
        }
        return applicationdata;
    }

    /**
     * @param newDocName
     *            String
     * @param doc
     *            WTDocument
     * @return boolean
     * @description
     */
    public static boolean documentRename(String newDocName, WTDocument doc)
            throws WTException {
        LOGGER.info("newDocName = " + newDocName);
        boolean result = false;
        try {
            // if the same as original then return true
            if (newDocName.equals(doc.getName())) {
                result = true;
            }
            else {
                WTDocumentMaster docmaster = (WTDocumentMaster) doc.getMaster();
                WTDocumentMasterIdentity docmasteridentity = (WTDocumentMasterIdentity) docmaster
                        .getIdentificationObject();
                docmasteridentity.setName(newDocName);
                docmaster = (WTDocumentMaster) IdentityHelper.service
                        .changeIdentity(docmaster, docmasteridentity);
                String newName = docmaster.getName();
                if (newName.equals(newDocName)) {
                    result = true;
                }
            }
        } catch (WTPropertyVetoException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e, e.getLocalizedMessage());
        }
        return result;
    }

    /**
     * addAttachments
     * 
     * @param doc
     *            wt document instance
     * @param filePath
     *            file absolute server path
     * @param fileName
     *            file name
     * @throws WTException
     *             Windchill exception
     */
    public static void addAttachments(ContentHolder holder, String filePath,
            String fileName) throws WTException {
        try {
            QueryResult qr = ContentHelper.service.getContentsByRole(holder,
                    ContentRoleType.SECONDARY);
            while (qr.hasMoreElements()) {
                ApplicationData oAppData = (ApplicationData) qr.nextElement();
                String strFileName = oAppData.getFileName();
                if (strFileName != null
                        && strFileName.trim().equalsIgnoreCase(fileName)) {
                    ContentServerHelper.service.deleteContent(holder, oAppData);
                }
            }
            addContent(holder, filePath, fileName, ContentRoleType.SECONDARY);
        } catch (Exception e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        }
    }

    /**
     * Add primary content for a document.
     * 
     * @param doc
     *            document instance
     * @param filePath
     *            file absolute path
     * @param fileName
     *            file name
     * @throws WTException
     *             Windchill exception
     */
    public static void addPrimaryContent(WTDocument doc, String filePath,
            String fileName) throws WTException {
        try {
            ContentHolder contentHolder = ContentHelper.service
                    .getContents(doc);
            ApplicationData applicationData = (ApplicationData) ContentHelper
                    .getPrimary((FormatContentHolder) contentHolder);
            if (applicationData != null) {
                try {
                    ContentServerHelper.service.deleteContent(doc,
                            applicationData);
                } catch (WTPropertyVetoException e) {
                    LOGGER.error(e.getLocalizedMessage());
                    throw new WTException(e);
                }
            }
        } catch (PropertyVetoException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        }
        addContent(doc, filePath, fileName, ContentRoleType.PRIMARY);
    }

    /**
     * Add the contentHolder attenchMent
     * 
     * @param holder
     * @param filePath
     * @param fileName
     * @param contentType
     * @throws WTException
     */
    private static void addContent(ContentHolder holder, String filePath,
            String fileName, ContentRoleType contentType) throws WTException {
        ApplicationData applicationData = ApplicationData
                .newApplicationData(holder);
        try {
            applicationData.setRole(contentType);
            applicationData = (ApplicationData) PersistenceHelper.manager
                    .save(applicationData);
            applicationData = ContentServerHelper.service.updateContent(holder,
                    applicationData, filePath);
            applicationData.setFileName(fileName);
            applicationData = (ApplicationData) PersistenceHelper.manager
                    .modify(applicationData);
        } catch (IOException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        } catch (PropertyVetoException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        }
    }

    /**
     * saveFiletoAttachment
     * 
     * @param ContentHolder
     * @param String
     * @return
     * @throws WTException
     */
    public static void saveFiletoAttachment(ContentHolder contentholder,
            String filename) throws WTException, WTPropertyVetoException,
            PropertyVetoException, IOException {
        ApplicationData appData = ApplicationData
                .newApplicationData(contentholder);
        appData.setRole(ContentRoleType.SECONDARY);
        ContentServerHelper.service.updateContent(contentholder, appData,
                filename);
    }

    /**
     * deleteContentByFileName
     * 
     * @param ContentHolder
     * @param String
     * @return
     * @throws WTException
     */
    public static ContentHolder deleteContentByFileName(ContentHolder holder1,
            String fileName) throws WTException {
        ContentHolder holder = holder1;
        if (fileName == null) {
            return holder;
        }
        try {
            holder = ContentHelper.service.getContents(holder);
            List<?> vContentList = ContentHelper.getContentList(holder);
            int iSize = vContentList.size();
            for (int j = 0; j < iSize; j++) {
                ContentItem contentitem = (ContentItem) vContentList.get(j);
                String strFileName = ((ApplicationData) contentitem)
                        .getFileName();
                if (fileName.equals(strFileName)) {
                    ContentServerHelper.service.deleteContent(holder,
                            contentitem);
                }
            }
            holder = (FormatContentHolder) PersistenceHelper.manager
                    .refresh(holder);
        } catch (PropertyVetoException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        }
        return holder;
    }

    /**
     * deleteContents
     * 
     * @param WTDocument
     * @return WTDocument
     * @throws WTException
     */
    public static WTDocument deleteContents(WTDocument doc) throws WTException {
        FormatContentHolder holder = null;
        try {
            holder = (FormatContentHolder) ContentHelper.service
                    .getContents(doc);
            List<?> items = ContentHelper.getContentListAll(holder);
            for (int i = 0; i < items.size(); i++) {
                ContentItem item = (ContentItem) items.get(i);
                ContentServerHelper.service.deleteContent(holder, item);
            }
            holder = (FormatContentHolder) PersistenceHelper.manager
                    .refresh(holder);
        } catch (PropertyVetoException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        }

        return (WTDocument) holder;
    }

    /**
     * 
     * @param doc
     * @param filePath
     * @param fileName
     * @return
     * @throws FileNotFoundException
     * @throws WTException
     * @throws PropertyVetoException
     * @throws IOException
     */
    public static WTDocument updateContent(WTDocument doc, String filePath,
            String fileName,ContentRoleType role) throws WTException {
        LOGGER.debug("filePath:" + filePath+",fileName:" + fileName);
        ApplicationData applicationdata = ApplicationData
                .newApplicationData(doc);
//        ContentHolder ch = null;
        try {
//            applicationdata.setFileName(fileName);
//            applicationdata.setUploadedFromPath(filePath);
            applicationdata.setRole(role);
            
//            ContentServerHelper.service.deleteContent(doc,
//                    ContentHelper.getPrimary((FormatContentHolder) ch));
//            ch = (FormatContentHolder) PersistenceHelper.manager.refresh(ch);
            ContentServerHelper.service.updateContent(doc, applicationdata,filePath + File.separator + fileName);
            ContentServerHelper.service.updateHolderFormat(doc);
            doc = (WTDocument) PersistenceHelper.manager.refresh((Persistable)doc, true, true);
        } catch (WTPropertyVetoException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        } catch (PropertyVetoException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        } catch (FileNotFoundException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        } catch (IOException e) {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        }

        return (WTDocument) doc;
    }

    /**
     * Get document by number version an diteration
     * 
     * @param number
     * @param version
     * @param iteration
     * @return
     * @throws WTException
     */
    public static WTDocument getDocumentByNumberByVersionByIteration(
            String number, String version, String iteration) throws WTException {
        QuerySpec query = new QuerySpec();
        query.setAdvancedQueryEnabled(true);
        int docTable = query.appendClassList(WTDocument.class, true);
        int docMasterTable = query.appendClassList(WTDocumentMaster.class,
                false);
        String[] aliases = new String[2];
        aliases[0] = query.getFromClause().getAliasAt(docTable);
        aliases[1] = query.getFromClause().getAliasAt(docMasterTable);

        TableColumn sVersion = new TableColumn(aliases[0],
                "VERSIONIDA2VERSIONINFO");
        TableColumn sIter = new TableColumn(aliases[0],
                "ITERATIONIDA2ITERATIONINFO");
        TableColumn iDA3MASTERREFERENCE = new TableColumn(aliases[0],
                "IDA3MASTERREFERENCE");

        TableColumn numberCol = new TableColumn(aliases[1], "WTDOCUMENTNUMBER");
        TableColumn iDA2A2Col = new TableColumn(aliases[1], "IDA2A2");

        query.appendWhere(new SearchCondition(numberCol, SearchCondition.EQUAL,
                new ConstantExpression(number.toUpperCase())));
        query.appendAnd();

        query.appendWhere(new SearchCondition(iDA2A2Col, SearchCondition.EQUAL,
                iDA3MASTERREFERENCE));
        query.appendAnd();

        query.appendWhere(new SearchCondition(sVersion, SearchCondition.EQUAL,
                new ConstantExpression(version)));
        query.appendAnd();

        query.appendWhere(new SearchCondition(sIter, SearchCondition.EQUAL,
                new ConstantExpression(iteration)));

        QueryResult qr = PersistenceHelper.manager.find((StatementSpec) query);

        WTDocument document = null;
        if (qr.hasMoreElements()) {
            Object obj[] = (Object[]) qr.nextElement();
            document = (WTDocument) obj[0];
        }
        return document;
    }

    /**
     * get Workbook by primaryBusinessObject
     * 
     * @param pbo
     * @return the object to found or null if not found.
     */
    public static Workbook getWorkbook(WTObject pbo) {
        Workbook workbook = null;
        if (pbo != null && (pbo instanceof WTDocument)) {
            // get document
            WTDocument wtdocument = (WTDocument) pbo;
            // get ApplicationData
            InputStream inputStream = null;
            try {
                ApplicationData applicationdata = DocUtil
                        .getPrimaryContent(wtdocument);
                if (applicationdata != null) {
                    // get Workbook
                    inputStream = ContentServerHelper.service
                            .findContentStream(applicationdata);
                    workbook = WorkbookFactory.create(inputStream);
                }
            } catch (WTException e) {
                LOGGER.error(e.getMessage(), e);
            } catch (IOException e) {
                LOGGER.error(e.getMessage(), e);
            } catch (InvalidFormatException e) {
                LOGGER.error(e.getMessage(), e);
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }

                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        }
        return workbook;
    }

    /**
     * create wtdocument in windchill by name, container,folder and type
     * type default is WTDocument, folder default value is Default,
     * name and container must has value.
     * 
     * @param strCsv
     * @param strExcel
     * @param docName
     * @param designLab
     * @return
     * @throws WTException
     */
    public static WTDocument createLoaddoc(String docName, String containenname, String folder, String type)
            throws WTException {
        LOGGER.debug("=============create doc begin============");
        if (docName == null || "".equals(docName)) {
            return null;
        }
        if (containenname == null || "".equals(containenname)) {
            return null;
        }
        WTDocument document = WTDocument.newWTDocument();
        try {
            TypeDefinitionReference typeDefinitionRef = null;
            if (type == null || "".equals(type)) {
                typeDefinitionRef =
                        TypedUtility.getTypeDefinitionReference("wt.doc.WTDocument");
            } else {
                typeDefinitionRef =
                        TypedUtility.getTypeDefinitionReference(type);
            }
            document.setTypeDefinitionReference(typeDefinitionRef);
            document.setName(docName);
            // Set Container
            WTContainer container = WCUtil.getWtContainerByName(containenname);
            // Set Folder
            Folder docFold = null;
            if (folder == null || "".equals(folder)) {
                docFold = FolderHelper.service.getFolder("Default", WTContainerRef.newWTContainerRef(container));
            } else {
                docFold = FolderHelper.service.getFolder("Default/" + folder,
                        WTContainerRef.newWTContainerRef(container));
            }
            FolderHelper.assignLocation((FolderEntry) document, docFold);
            // Set Container
            PersistenceHelper.manager.save(document);
            LOGGER.debug("=============create doc end============");
        } catch (WTException e) {
            LOGGER.error(e.getLocalizedMessage(), e);
            throw new WTException(e);
        } catch (WTPropertyVetoException e) {
            LOGGER.error(e.getLocalizedMessage(), e);
            throw new WTException(e);
        }
        return document;
    }

    /**
     * createWTDocument
     * 
     * @param String
     *            name
     * @param String
     *            number
     * @param String
     *            type
     * @param container
     *            WTContainer
     * @param String
     *            folderPath
     * @return WTDocument
     * @throws Exception
     */
    public static WTDocument createWTDocument(String name, String number, String type, String description,
            String containerName, String folderPath) throws WTException
    {
        TypeIdentifier objType = TypeHelper.getTypeIdentifier(type);
        WTDocument doc = (WTDocument) TypeHelper.newInstance(objType);
        try
        {
            doc.setName(name);
            if (number != null && !"".equals(number.trim()))
            {
                doc.setNumber(number);
            }
            if (description != null && !"".equals(description.trim()))
            {
                doc.setDescription(description);
            }
            WTContainer container = WCUtil.getWtContainerByName(containerName);
            if(container==null){
            	throw new WTException("The '"+containerName+"' container does not exist.");
            }
            WTContainerRef containerRef = WTContainerRef.newWTContainerRef(container);
            doc.setContainerReference(containerRef);
            Folder folder = getFolder(folderPath, containerRef);
            if (folder != null)
            {
                FolderHelper.assignLocation((FolderEntry) doc, folder);
            }   
        } catch (WTPropertyVetoException e)
        {
            LOGGER.error(e.getLocalizedMessage());
            throw new WTException(e);
        }
        doc = (WTDocument) PersistenceHelper.manager.save(doc);
        return doc;
    }

    /**
     * get folder by folder name and containerref
     * @param folderName
     * @param containerRef
     * @return
     * @throws WTException
     */
    public static Folder getFolder(String folderName, WTContainerRef containerRef) throws WTException{
		Folder location = null;
		try {
			location = FolderHelper.service.getFolder(folderName,containerRef);
			 LOGGER.debug("Folder is :" + folderName);
		} catch (WTException e) {
			location = null;
		}
		// create folder if there is no such location
		if (location == null) {
			location = FolderHelper.service.saveFolderPath(folderName,containerRef);
		}
		return location;
	}
    
    /**
     * 
     * @description create wtdocument in windchill by number, name, container,folder and type
     * type default is WTDocument, folder default value is Default,
     * name and container must has value.
     * @author jgao
     * @date Jul 21, 2015
     * @param docNumber
     * @param docName
     * @param containenname
     * @param folder
     * @param type
     * @return
     * @throws WTException
     */
    public static WTDocument createDoc(String docNumber, String docName, String containenname, String folder, String type)
            throws WTException {
        if (docName == null || "".equals(docName)) {
            return null;
        }
        if (containenname == null || "".equals(containenname)) {
            return null;
        }
        WTDocument document = WTDocument.newWTDocument();
        try {
            TypeDefinitionReference typeDefinitionRef = null;
            if (type == null || "".equals(type)) {
                typeDefinitionRef =
                        TypedUtility.getTypeDefinitionReference("wt.doc.WTDocument");
            } else {
                typeDefinitionRef =
                        TypedUtility.getTypeDefinitionReference(type);
            }
            document.setTypeDefinitionReference(typeDefinitionRef);
            document.setName(docName);
            if(docNumber != null && !docNumber.isEmpty())
            {
                document.setNumber(docNumber);
            }
            // Set Container
            WTContainer container = WCUtil.getWtContainerByName(containenname);
            // Set Folder
            Folder docFold = null;
            if (folder == null || "".equals(folder)) {
                docFold = FolderHelper.service.getFolder("Default", WTContainerRef.newWTContainerRef(container));
            } else {
                docFold = FolderHelper.service.getFolder("Default/" + folder,
                        WTContainerRef.newWTContainerRef(container));
            }
            FolderHelper.assignLocation((FolderEntry) document, docFold);
            // Set Container
            PersistenceHelper.manager.save(document);
        } catch (WTException e) {
            LOGGER.error(e.getLocalizedMessage(), e);
            throw new WTException(e);
        } catch (WTPropertyVetoException e) {
            LOGGER.error(e.getLocalizedMessage(), e);
            throw new WTException(e);
        }
        return document;
    }
    
    /**
     * get document version list, just as A.1, A.2 and so on.
     * 
     * @param docNum
     * @return
     */
    public static List<String> getDocumentVersionList(String docNum)
            throws WTException {

        if (!RemoteMethodServer.ServerFlag) {
            try {

                return (List<String>) RemoteMethodServer.getDefault().invoke(
                        "getDocumentVersionList", DocUtil.class.getName(),
                        null, new Class[] { String.class },
                        new Object[] { docNum });
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
                throw new WTException(e);
            }

        } else {

            QuerySpec spec = new QuerySpec(WTDocument.class);
            spec.appendSearchCondition(new SearchCondition(WTDocument.class,
                    WTDocument.NUMBER, SearchCondition.EQUAL, docNum, true));

            QueryResult results = PersistenceHelper.manager.find(spec);
            List<String> list = new ArrayList<String>();
            TreeMap<String, String> sortMap = new TreeMap<String, String>();

            NumberFormat nf = NumberFormat.getInstance();
            nf.setMinimumIntegerDigits(5);
            nf.setMaximumIntegerDigits(5);
            nf.setGroupingUsed(false);

            while (results.hasMoreElements()) {
                WTDocument doc = (WTDocument) results.nextElement();
                sortMap.put(
                        doc.getVersionIdentifier().getValue()
                                + "."
                                + nf.format(Integer.parseInt(doc
                                        .getIterationIdentifier().getValue())),
                        doc.getVersionIdentifier().getValue() + "."
                                + doc.getIterationIdentifier().getValue());
            }
            for (String key : sortMap.keySet()) {
                list.add(sortMap.get(key));
            }
            return list;

        }
    }
    
    public static ApplicationData updateApplicationDataToDoc(WTDocument document, String fileName,
            String filePath, boolean isPrimary) throws WTException, WTPropertyVetoException,
            java.beans.PropertyVetoException, IOException {
        ApplicationData applicationdata = ApplicationData.newApplicationData(document);
        applicationdata.setFileName(fileName);
        applicationdata.setUploadedFromPath(filePath);
        if (isPrimary) {
            applicationdata.setRole(ContentRoleType.PRIMARY);
        }
        wt.content.ContentHolder ch = wt.content.ContentHelper.service.getContents(document);
        // delete original ApplicationData
        if (!isPrimary) {// Attachment
            Vector apps = ContentHelper.getApplicationData(ch);
            for (int i = 0; i < apps.size(); i++) {
                ApplicationData app = (ApplicationData) apps.elementAt(i);
                if (app.getFileName().equals(fileName)) {
                    ContentServerHelper.service.deleteContent(ch, app);
                }
            }
        } else {// Primary
            ContentItem item = (ContentItem) ContentHelper.service.getPrimary(document);
            ContentServerHelper.service.deleteContent(ch, item);
        }
        if (!RemoteMethodServer.ServerFlag) {//
            try {
                Class aclass[] = { ContentHolder.class, ApplicationData.class, String.class };
                Object aobj[] = { ch, applicationdata, filePath + fileName };
                RemoteMethodServer.getDefault().invoke("addApplicationDataToDoc", DocUtil.class.getName(),
                        null, aclass, aobj);
            } catch (Exception e) {
                LOGGER.error("-------[addApplicationDataToDoc]------------" + e.getLocalizedMessage());
            }
        } else {// 
            ContentServerHelper.service.updateContent(ch, applicationdata, filePath + fileName);
            try {
                ContentServerHelper.service.updateHolderFormat((FormatContentHolder) document);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return applicationdata;
    }

    /**
     * Get Attachment by pre-fix name
     * @param doc
     * @param preFix
     * @return
     */
    public static ApplicationData getAttachement(WTDocument doc,String preFix){
        QueryResult qr;
        try {
            qr = ContentHelper.service.getContentsByRole(doc, ContentRoleType.SECONDARY);
            while (qr.hasMoreElements()) {
                ApplicationData appData = (ApplicationData) qr.nextElement(); 
                if(appData != null){
                    String fileName = appData.getFileName();
                    if(fileName.startsWith(preFix)){
                        return appData;
                    }
                }
            }
        } catch (WTException e) {
            e.printStackTrace();
        }
        return null;
        
    }
    
    /**
     * revise WTDocument
     * 
     * @param doc
     *            WTDocument
     * @return WTDocument
     * @throws WTException
     */
    public static WTDocument reviseWTDocument(WTDocument document, String comment) throws WTException {
        WTDocument wtdocument = document;
        try {
            if (wtdocument == null) {
                return null;
            }
            WTContainer container = wtdocument.getContainer();
            WTContainerRef containerRef = WTContainerRef.newWTContainerRef(container); // container.getContainerReference();//
            TeamReference teamReference = wtdocument.getTeamId();
            Folder oldFoler = FolderHelper.getFolder(wtdocument);
            if (oldFoler == null) {
                String strLocation = wtdocument.getLocation();
                oldFoler = FolderHelper.service.getFolder(strLocation, containerRef);
            }

            wtdocument = (WTDocument) wt.vc.VersionControlHelper.service.newVersion((wt.vc.Versioned) wtdocument);
            if (teamReference != null) {
                wtdocument.setTeamId(teamReference);
            }
            VersionControlHelper.setNote(wtdocument, comment == null ? "" : comment);
            wtdocument.setContainer(container);

            FolderHelper.assignLocation((FolderEntry) wtdocument, oldFoler);

            wtdocument = (WTDocument) PersistenceHelper.manager.save(wtdocument);
            wtdocument = (WTDocument) PersistenceHelper.manager.refresh(wtdocument);

        } catch (Exception e) {
            LOGGER.error("Auto Revise Failed :" + e.toString());
            LOGGER.error("Original comment :" + comment);
            throw new WTException(e);
        }
        return wtdocument;
    }

    public static List<WTDocument> queryWTDocument(String state, String softType) throws WTException {
        String[] states = (state != null && !state.trim().isEmpty()) ? new String[] { state.trim() } : null;
        String[] softTypes = (softType != null && !softType.trim().isEmpty()) ? new String[] { softType } : null;
        return queryWTDocument(states, softTypes);
    }

    /**
     * Queries WTDocument objects.
     * 
     * @param states
     *            The internal name of life cycle states, e.g. PRODUCTIONRELEASED.
     * @param softTypes
     *            The soft types of WTDocument objects, e.g. wt.doc.WTDocument|com.lenovo.ElementType|com.lenovo.IMG
     * @return A list of WTDocument objects.
     * @throws WTException
     *             Failed to query WTDocument objects with the given parameters.
     * @author Luo Jiao, August 31, 2015
     */
    public static List<WTDocument> queryWTDocument(String[] states, String[] softTypes) throws WTException {
        LOGGER.debug(">>>>> Enter => queryWTDocument(String[] states, String[] softTypes)");
        List<WTDocument> result = new ArrayList<WTDocument>();
        if ((states == null || states.length == 0) && (softTypes == null || softTypes.length == 0)) {
            return result;
        }
        try {
            QuerySpec qs = new QuerySpec();
            int indexWTDocument = qs.appendClassList(WTDocument.class, true);
            WhereExpression where = null;
            // Specifies the soft types of target object.
            if (softTypes != null && softTypes.length > 0) {
                int indexWTTypeDefinition = qs.appendClassList(WTTypeDefinition.class, false);
                int indexWTTypeDefinitionMaster = qs.appendClassList(WTTypeDefinitionMaster.class, false);
                where = new SearchCondition(new ClassAttribute(WTDocument.class, "typeDefinitionReference.key.id"),
                        SearchCondition.EQUAL, new ClassAttribute(WTTypeDefinition.class,
                                "thePersistInfo.theObjectIdentifier.id"));
                qs.appendWhere(where, new int[] { indexWTDocument, indexWTTypeDefinition });

                where = new SearchCondition(new ClassAttribute(WTTypeDefinition.class, "masterReference.key.id"),
                        SearchCondition.EQUAL, new ClassAttribute(WTTypeDefinitionMaster.class,
                                "thePersistInfo.theObjectIdentifier.id"));
                qs.appendAnd();
                qs.appendWhere(where, new int[] { indexWTTypeDefinition, indexWTTypeDefinitionMaster });

                if (softTypes.length == 1) {
                    where = new SearchCondition(WTTypeDefinitionMaster.class, "intHid", SearchCondition.EQUAL,
                            softTypes[0]);
                } else {
                    where = new SearchCondition(WTTypeDefinitionMaster.class, "intHid", softTypes, true);
                }
                qs.appendAnd();
                qs.appendWhere(where, new int[] { indexWTTypeDefinitionMaster });
            }
            // Specifies the life cycle state of target object.
            if (states != null && states.length > 0) {
                if (states.length == 1) {
                    where = new SearchCondition(WTDocument.class, "state.state", SearchCondition.EQUAL, states[0]);
                } else {
                    where = new SearchCondition(WTDocument.class, "state.state", states, true);
                }
                if (qs.getConditionCount() > 0 && qs.getWhere().endsWith(")")) {
                    qs.appendAnd();
                }
                qs.appendWhere(where, new int[] { indexWTDocument });
            }
            // Sorted by modifying time in descending order.
            OrderBy orderby = new OrderBy(new ClassAttribute(WTDocument.class, "thePersistInfo.modifyStamp"), true);
            qs.appendOrderBy(orderby, new int[] { indexWTDocument });
            LOGGER.debug(">>>>> queryWTDocument(): qs=" + qs);
            QueryResult qr = PersistenceHelper.manager.find((StatementSpec) qs);
            LOGGER.debug(">>>>> queryWTDocument(): qr=" + qr);
            if (qr != null) {
                ObjectVector vector = new ObjectVector();
                while (qr.hasMoreElements()) {
                    Object obj = qr.nextElement();
                    if (obj instanceof Persistable[]) {
                        Persistable[] apersist = (Persistable[]) obj;
                        vector.addElement(apersist[0]);
                    } else {
                        vector.addElement(obj);
                    }
                }
                if (!vector.isEmpty()) {
                    qr = new QueryResult(vector);
                }
                qr = (new LatestConfigSpec()).process(qr);
            }
            if (qr != null) {
                while (qr.hasMoreElements()) {
                    result.add((WTDocument) qr.nextElement());
                }
            }
            LOGGER.debug(">>>>> queryWTDocument(): result.size()=" + result.size());
            return result;
        } catch (Exception e) {
            String errorMsg = MessageFormat
                    .format(">>>>> Failed to query WTDocument objects with the given parameters: states-[{0}], softTypes-[{1}].",
                            states, softTypes);
            LOGGER.error(">>>>>" + errorMsg, e);
            throw new WTException(e, errorMsg);
        }
    }

    /**
     * Queries WTDocument objects.
     * 
     * @param number
     *            The number of WTDocument object.
     * @param name
     *            The name of WTDocument object.
     * @param state
     *            The internal name of life cycle state, e.g. INWORK.
     * @param version
     *            The version of WTDocument object.
     * @param iteration
     *            The iteration of WTDocument object.
     * @return A QueryResult contains WTDocument objects, sorted by modifying time in descending order.
     * @throws WTException
     *             Failed to query WTDocument objects with the given parameters.
     * @author Luo Jiao, July 17, 2015
     */
    public static QueryResult queryWTDocument(String number, String name, String state, String version, String iteration)
            throws WTException {
        try {
            QuerySpec queryspec = new QuerySpec(WTDocument.class);
            WhereExpression where = null;
            // Specifies the iteration of WTDocument object.
            if (iteration != null && !iteration.trim().isEmpty()) {
                where = new SearchCondition(WTDocument.class, "iterationInfo.identifier.iterationId",
                        SearchCondition.EQUAL, iteration);
                queryspec.appendWhere(where, new int[] { 0 });
            }
            // Specifies the version of WTDocument object.
            if (version != null && !version.trim().isEmpty()) {
                where = new SearchCondition(WTDocument.class, "versionInfo.identifier.versionId",
                        SearchCondition.EQUAL, version);
                if (queryspec.getConditionCount() > 0 && queryspec.getWhere().endsWith(")")) {
                    queryspec.appendAnd();
                }
                queryspec.appendWhere(where, new int[] { 0 });
            }
            // Specifies the life cycle state of WTDocument object.
            if (state != null && !state.trim().isEmpty()) {
                where = new SearchCondition(WTDocument.class, WTDocument.LIFE_CYCLE_STATE, SearchCondition.EQUAL, state);
                if (queryspec.getConditionCount() > 0 && queryspec.getWhere().endsWith(")")) {
                    queryspec.appendAnd();
                }
                queryspec.appendWhere(where, new int[] { 0 });
            }
            // Specifies the name of WTDocument object.
            if (name != null && !name.trim().isEmpty()) {
                where = new SearchCondition(WTDocument.class, WTDocument.NAME, SearchCondition.EQUAL, name);
                if (queryspec.getConditionCount() > 0 && queryspec.getWhere().endsWith(")")) {
                    queryspec.appendAnd();
                }
                queryspec.appendWhere(where, new int[] { 0 });
            }
            // Specifies the number of WTDocument object.
            if (number != null && !number.trim().isEmpty()) {
                where = new SearchCondition(WTDocument.class, WTDocument.NUMBER, SearchCondition.EQUAL, number);
                if (queryspec.getConditionCount() > 0 && queryspec.getWhere().endsWith(")")) {
                    queryspec.appendAnd();
                }
                queryspec.appendWhere(where, new int[] { 0 });
            }
            // Sorted by modifying time in descending order.
            OrderBy orderby = new OrderBy(new ClassAttribute(WTDocument.class, "thePersistInfo.modifyStamp"), true);
            queryspec.appendOrderBy(orderby, new int[] { 0 });
            System.out.println("KiraNote:queryspec:" + queryspec.toString());
            return PersistenceHelper.manager.find((StatementSpec) queryspec);
        } catch (Exception e) {
            String errorMsg = MessageFormat.format(
                    "Failed to query WTDocument objects with the given parameters: number-[{0}],"
                            + " name-[{1}], life cycle state-[{2}], version-[{3}], iteration-[{4}].", number, name,
                    state, version, iteration);
            LOGGER.error(">>>>>" + errorMsg, e);
            throw new WTException(e, errorMsg);
        }
    }

    /**
     * Queries the WTDocument object by specifying its number and life cycle state, returns the latest iteration of the
     * specified version.
     * 
     * @param number
     *            The number of WTDocument object.
     * @param state
     *            The state of WTDocument object.
     * @param version
     *            The version of WTDocument object (e.g. "A", "AB"). Note: do not include iteration.
     * @return the WTDocument object.
     * @throws WTException
     *             Failed to query the WTDocument object.
     * @author Luo Jiao, July 17, 2015
     */
    public static WTDocument getWTDocument(String number, String state, String version) throws WTException {
        QueryResult result = queryWTDocument(number, null, state, version, null);
        if (result != null && result.hasMoreElements()) {
            return (WTDocument) result.nextElement();
        }
        return null;
    }

    /**
     * Queries EPMDocument objects.
     * 
     * @param number
     *            The number of EPMDocument object.
     * @param name
     *            The name of EPMDocument object.
     * @param state
     *            The internal name of life cycle state, e.g. INWORK.
     * @param version
     *            The version of EPMDocument object.
     * @param iteration
     *            The iteration of EPMDocument object.
     * @return A QueryResult contains EPMDocument objects, sorted by modifying time in descending order.
     * @throws WTException
     *             Failed to query EPMDocument objects with the given parameters.
     * @author Luo Jiao, July 17, 2015
     */
    public static QueryResult queryEPMDocument(String number, String name, String state, String version,
            String iteration) throws WTException {
        try {
            QuerySpec queryspec = new QuerySpec(EPMDocument.class);
            WhereExpression where = null;
            // Specifies the iteration of EPMDocument object.
            if (iteration != null && !iteration.trim().isEmpty()) {
                where = new SearchCondition(EPMDocument.class, "iterationInfo.identifier.iterationId",
                        SearchCondition.EQUAL, iteration);
                queryspec.appendWhere(where, new int[] { 0 });
            }
            // Specifies the version of EPMDocument object.
            if (version != null && !version.trim().isEmpty()) {
                where = new SearchCondition(EPMDocument.class, "versionInfo.identifier.versionId",
                        SearchCondition.EQUAL, version);
                if (queryspec.getConditionCount() > 0 && queryspec.getWhere().endsWith(")")) {
                    queryspec.appendAnd();
                }
                queryspec.appendWhere(where, new int[] { 0 });
            }
            // Specifies the life cycle state of EPMDocument object.
            if (state != null && !state.trim().isEmpty()) {
                where = new SearchCondition(EPMDocument.class, EPMDocument.LIFE_CYCLE_STATE, SearchCondition.EQUAL,
                        state);
                if (queryspec.getConditionCount() > 0 && queryspec.getWhere().endsWith(")")) {
                    queryspec.appendAnd();
                }
                queryspec.appendWhere(where, new int[] { 0 });
            }
            // Specifies the name of EPMDocument object.
            if (name != null && !name.trim().isEmpty()) {
                where = new SearchCondition(EPMDocument.class, EPMDocument.NAME, SearchCondition.EQUAL, name);
                if (queryspec.getConditionCount() > 0 && queryspec.getWhere().endsWith(")")) {
                    queryspec.appendAnd();
                }
                queryspec.appendWhere(where, new int[] { 0 });
            }
            
            // Specifies the number of EPMDocument object.
            if (number != null && !number.trim().isEmpty()) {
                where = new SearchCondition(EPMDocument.class, EPMDocument.NUMBER, SearchCondition.EQUAL, number);
                if (queryspec.getConditionCount() > 0 && queryspec.getWhere().endsWith(")")) {
                    queryspec.appendAnd();
                }
                queryspec.appendWhere(where, new int[] { 0 });
            }
            //add by cuihan 20160908 start
            queryspec.appendAnd(); 
            where= new SearchCondition(EPMDocument.class, WTAttributeNameIfc.LATEST_ITERATION,
            		SearchCondition.IS_TRUE);
            queryspec.appendWhere(where,new int[]{0});
            //add by cuihan 20160908 end
            // Sorted by modifying time in descending order.
            OrderBy orderby = new OrderBy(new ClassAttribute(EPMDocument.class, "thePersistInfo.modifyStamp"), true);
            queryspec.appendOrderBy(orderby, new int[] { 0 });
            LOGGER.debug(">>>>> DocUtil.queryEPMDocument(): queryspec=" + queryspec);
            return PersistenceHelper.manager.find((StatementSpec) queryspec);
        } catch (Exception e) {
            String errorMsg = MessageFormat.format(
                    "Failed to query EPMDocument objects with the given parameters: number-[{0}],"
                            + " name-[{1}], life cycle state-[{2}], version-[{3}], iteration-[{4}].", number, name,
                    state, version, iteration);
            LOGGER.error(">>>>>" + errorMsg, e);
            throw new WTException(e, errorMsg);
        }
    }

    /**
     * Gets EPMDocument object by specifying its number, life cycle state and version, and returns the latest
     * iteration.
     * 
     * @param number
     *            The number of EPMDocument object.
     * @param state
     *            The internal name of life cycle state, e.g. INWORK.
     * @param version
     *            The version of EPMDocument object (e.g. "A", "AB"). Note: do not include iteration.
     * @return the EPMDocument object.
     * @throws WTException
     *             Failed to query EPMDocument objects.
     * @author Luo Jiao, February 8, 2016
     */
    public static EPMDocument getEPMDocument(String number, String state, String version) throws WTException {
        QueryResult result = queryEPMDocument(number, null, state, version, null);
        if (result != null && result.hasMoreElements()) {
            return (EPMDocument) result.nextElement();
        }
        return null;
    }
    /**
     * Gets EPMDocument object by specifying its number and version, and returns the latest iteration.
     * 
     * @param number
     *            The number of EPMDocument object.
     * @param version
     *            The version of EPMDocument object (e.g. "A", "AB"). Note: do not include iteration.
     * @return the EPMDocument object.
     * @throws WTException
     *             Failed to query EPMDocument objects.
     * @author Luo Jiao, July 17, 2015
     */
    public static EPMDocument getEPMDocument(String number, String version) throws WTException {
        QueryResult result = queryEPMDocument(number, null, null, version, null);
        if (result != null && result.hasMoreElements()) {
            return (EPMDocument) result.nextElement();
        }
        return null;
    }
    
    /**
     * 
     * @param number
     * @return
     * @throws WTException
     */
    public static EPMDocument getEpmdocumentByNumber(String number)throws WTException{

        EPMDocument epmdoc=null;
        String condition=SearchCondition.EQUAL;
        String keyWord=number;
      
        QuerySpec qs=new QuerySpec();
        int epmId=qs.addClassList(EPMDocument.class, true);
        int epmmId=qs.addClassList(EPMDocumentMaster.class, false);
        WhereExpression where=null;
        ClassAttribute epm=new ClassAttribute(EPMDocument.class,"masterReference.key.id");
        ClassAttribute epmm=new ClassAttribute(EPMDocumentMaster.class,WTAttributeNameIfc.ID_NAME);
        where=new SearchCondition(epm,SearchCondition.EQUAL,epmm);
        qs.appendWhere(where,new int[]{epmId,epmmId});
        qs.appendAnd(); 
        where= new SearchCondition(EPMDocument.class, WTAttributeNameIfc.LATEST_ITERATION,
                SearchCondition.IS_TRUE);
        qs.appendWhere(where,new int[]{epmId});
        qs.appendAnd();
        where=new SearchCondition(EPMDocumentMaster.class,EPMDocumentMaster.NUMBER,condition,keyWord);
        qs.appendWhere(where,new int[]{epmmId});
        QueryResult queryresult=PersistenceHelper.manager.find((StatementSpec)qs);
        LatestConfigSpec lcs = new LatestConfigSpec();
        ObjectVectorIfc obv=new ObjectVector();
        if(queryresult!=null){
            while(queryresult.hasMoreElements()){
                Object[] objs=(Object[]) queryresult.nextElement();
                Object obj=objs[0];
                obv.addElement(obj);
            }
        }
        QueryResult qr2=new QueryResult(obv);
        qr2=lcs.process(qr2);
        while(qr2.hasMoreElements()){
            
            epmdoc=(EPMDocument) qr2.nextElement();
            break;
        }
        
        return epmdoc;
     
    }

    /**
     * Gets the latest WTDocument object by WTDocumentMaster.
     * 
     * @param docMaster
     *            the given WTDocumentMaster object.
     * @return the latest WTDocument object of the given WTDocumentMaster.
     * @throws WTException
     *             Failed to get the latest WTDocument object by WTDocumentMaster.
     * @author Luo Jiao, July 23, 2015
     */
    public static WTDocument getLatestDoc(WTDocumentMaster docMaster) throws WTException {
        if (docMaster != null) {
            try {
                QueryResult qr = VersionControlHelper.service.allVersionsOf(docMaster);
                if (qr != null && qr.hasMoreElements()) {
                    return (WTDocument) qr.nextElement();
                }
            } catch (WTException e) {
                String errorMsg = MessageFormat.format(
                        "Failed to get the latest WTDocument object by WTDocumentMaster-[{0}].-[{0}].",
                        ((docMaster != null) ? docMaster.getDisplayIdentity() : null));
                LOGGER.error(">>>>>" + errorMsg, e);
                throw new WTException(e, errorMsg);
            }
        }
        return null;
    }

    /**
     * Gets the latest EPMDocument object by EPMDocumentMaster.
     * 
     * @param epmMaster
     *            the given EPMDocumentMaster object.
     * @return the latest EPMDocument object of the given EPMDocumentMaster.
     * @throws WTException
     *             Failed to get the latest EPMDocument object by EPMDocumentMaster.
     * @author Luo Jiao, July 23, 2015
     */
    public static EPMDocument getLatestEPMDoc(EPMDocumentMaster epmMaster) throws WTException {
        if (epmMaster != null) {
            try {
                QueryResult qr = VersionControlHelper.service.allVersionsOf(epmMaster);
                if (qr != null && qr.hasMoreElements()) {
                    return (EPMDocument) qr.nextElement();
                }
            } catch (WTException e) {
                String errorMsg = MessageFormat.format(
                        "Failed to get the latest EPMDocument object by EPMDocumentMaster-[{0}].",
                        ((epmMaster != null) ? epmMaster.getDisplayIdentity() : null));
                LOGGER.error(">>>>>" + errorMsg, e);
                throw new WTException(e, errorMsg);
            }
        }
        return null;
    }

    /**
     * Rename EPMDocument object to the given new name.
     * 
     * @param epmDoc
     *            the EPMDocument object to be renamed.
     * @param newName
     *            the new name of EPMDocument object.
     * @throws WTException
     *             Failed to rename the given EPMDocument object to new name.
     * @author Luo Jiao, July 27, 2015
     */
    public static void renameEPMDoc(EPMDocument epmDoc, String newName) throws WTException {
        if (epmDoc == null || newName == null || newName.isEmpty()) {
            LOGGER.error(MessageFormat.format(
                    ">>>>> Cannot rename the given EPMDocument object-[{0}] to new name-[{1}].",
                    ((epmDoc != null) ? epmDoc.getDisplayIdentity() : null), newName));
            return;
        }
        EPMDocumentMaster epmDocMaster = (EPMDocumentMaster) epmDoc.getMaster();
        WTPrincipal currentUser = null;
        try {
            currentUser = SessionHelper.manager.getPrincipal();
            SessionHelper.manager.setAdministrator();
            EPMDocumentMasterIdentity newIdentity = EPMDocumentMasterIdentity
                    .newEPMDocumentMasterIdentity(epmDocMaster);
            newIdentity.setName(newName);
            newIdentity.setNumber(epmDocMaster.getNumber());
            IdentityHelper.service.changeIdentity(epmDocMaster, newIdentity);
        } catch (Exception e) {
            String errorMsg = MessageFormat.format(
                    "Failed to rename the given EPMDocument object-[{0}] to new name-[{1}].",
                    ((epmDoc != null) ? epmDoc.getDisplayIdentity() : null), newName);
            LOGGER.error(">>>>>" + errorMsg, e);
            throw new WTException(e, errorMsg);
        } finally {
            try {
                SessionHelper.manager.setPrincipal(currentUser.getName());
            } catch (WTException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    /**
     * 
     * query WTDocument By name and softType.
     * 
     * 
     * @param name
     *              the WTDocument Name
     * @param softType
     *              the WTDocument softType
     * @return
     * @throws WTException
     * @author kira
     */
    public static List<WTDocument> queryWTDocumentByNameAndSoftType(String name, String softType) throws WTException {
        String[] softTypes = (softType != null && !softType.trim().isEmpty()) ? new String[] { softType } : null;
        LOGGER.debug(">>>>> Enter => queryWTDocumentByNameAndSoftType(String name, String softType)");
        List<WTDocument> result = new ArrayList<WTDocument>();
        try {
            QuerySpec qs = new QuerySpec();
            int indexWTDocument = qs.appendClassList(WTDocument.class, true);
            WhereExpression where = null;
            // Specifies the soft types of target object.
            if (softTypes != null && softTypes.length > 0) {
                int indexWTTypeDefinition = qs.appendClassList(WTTypeDefinition.class, false);
                int indexWTTypeDefinitionMaster = qs.appendClassList(WTTypeDefinitionMaster.class, false);
                where = new SearchCondition(new ClassAttribute(WTDocument.class, "typeDefinitionReference.key.id"),
                        SearchCondition.EQUAL, new ClassAttribute(WTTypeDefinition.class,
                                "thePersistInfo.theObjectIdentifier.id"));
                qs.appendWhere(where, new int[] { indexWTDocument, indexWTTypeDefinition });

                where = new SearchCondition(new ClassAttribute(WTTypeDefinition.class, "masterReference.key.id"),
                        SearchCondition.EQUAL, new ClassAttribute(WTTypeDefinitionMaster.class,
                                "thePersistInfo.theObjectIdentifier.id"));
                qs.appendAnd();
                qs.appendWhere(where, new int[] { indexWTTypeDefinition, indexWTTypeDefinitionMaster });

                if (softTypes.length == 1) {
                    where = new SearchCondition(WTTypeDefinitionMaster.class, "intHid", SearchCondition.EQUAL,
                            softTypes[0]);
                } else {
                    where = new SearchCondition(WTTypeDefinitionMaster.class, "intHid", softTypes, true);
                }
                qs.appendAnd();
                qs.appendWhere(where, new int[] { indexWTTypeDefinitionMaster });
            }
            // Specifies the name of target object.
            if (name != null) {
                SearchCondition searchCondi = new SearchCondition(WTDocument.class,
                        WTDocument.NAME, SearchCondition.EQUAL, name);
                qs.appendAnd();
                qs.appendWhere(searchCondi, new int[] { 0 });
            }
            
            
            // Sorted by modifying time in descending order.
            OrderBy orderby = new OrderBy(new ClassAttribute(WTDocument.class, "thePersistInfo.modifyStamp"), true);
            qs.appendOrderBy(orderby, new int[] { indexWTDocument });
            System.out.println(">>>>> queryWTDocument(): qs=" + qs);
            QueryResult qr = PersistenceHelper.manager.find((StatementSpec) qs);
            LOGGER.debug(">>>>> queryWTDocument(): qr=" + qr);
            if (qr != null) {
                ObjectVector vector = new ObjectVector();
                while (qr.hasMoreElements()) {
                    Object obj = qr.nextElement();
                    if (obj instanceof Persistable[]) {
                        Persistable[] apersist = (Persistable[]) obj;
                        vector.addElement(apersist[0]);
                    } else {
                        vector.addElement(obj);
                    }
                }
                if (!vector.isEmpty()) {
                    qr = new QueryResult(vector);
                }
                qr = (new LatestConfigSpec()).process(qr);
            }
            if (qr != null) {
                while (qr.hasMoreElements()) {
                    result.add((WTDocument) qr.nextElement());
                }
            }
            LOGGER.debug(">>>>> queryWTDocument(): result.size()=" + result.size());
            return result;
        } catch (Exception e) {
            String errorMsg = MessageFormat
                    .format(">>>>> Failed to query WTDocument objects with the given parameters: name-[{0}], softTypes-[{1}].",
                            name, softTypes);
            LOGGER.error(">>>>>" + errorMsg, e);
            throw new WTException(e, errorMsg);
        }
        
        
        
        
        
    }
    /**
     * 
     * @param name
     * @param softType ,such as:TypeConstants.WTDOCUMENT+ "|"+ TypeConstants.LSF + "|" + TypeConstants.GROUPLSF
     * @return
     * @throws WTException
     */
    public static WTDocument getWTDocumentByNameAndSoftType(String name, String softType) throws WTException {
        String[] softTypes = (softType != null && !softType.trim().isEmpty()) ? new String[] { softType } : null;
        LOGGER.debug(">>>>> Enter => queryWTDocumentByNameAndSoftType(String name, String softType)");
        WTDocument result = null;
        try {
            QuerySpec qs = new QuerySpec();
            int indexWTDocument = qs.appendClassList(WTDocument.class, true);
            WhereExpression where = null;
            // Specifies the soft types of target object.
            if (softTypes != null && softTypes.length > 0) {
                int indexWTTypeDefinition = qs.appendClassList(WTTypeDefinition.class, false);
                int indexWTTypeDefinitionMaster = qs.appendClassList(WTTypeDefinitionMaster.class, false);
                where = new SearchCondition(new ClassAttribute(WTDocument.class, "typeDefinitionReference.key.id"),
                        SearchCondition.EQUAL, new ClassAttribute(WTTypeDefinition.class,
                                "thePersistInfo.theObjectIdentifier.id"));
                qs.appendWhere(where, new int[] { indexWTDocument, indexWTTypeDefinition });

                where = new SearchCondition(new ClassAttribute(WTTypeDefinition.class, "masterReference.key.id"),
                        SearchCondition.EQUAL, new ClassAttribute(WTTypeDefinitionMaster.class,
                                "thePersistInfo.theObjectIdentifier.id"));
                qs.appendAnd();
                qs.appendWhere(where, new int[] { indexWTTypeDefinition, indexWTTypeDefinitionMaster });

                if (softTypes.length == 1) {
                    where = new SearchCondition(WTTypeDefinitionMaster.class, "intHid", SearchCondition.EQUAL,
                            softTypes[0]);
                } else {
                    where = new SearchCondition(WTTypeDefinitionMaster.class, "intHid", softTypes, true);
                }
                qs.appendAnd();
                qs.appendWhere(where, new int[] { indexWTTypeDefinitionMaster });
            }
            // Specifies the name of target object.
            if (name != null) {
                SearchCondition searchCondi = new SearchCondition(WTDocument.class,
                        WTDocument.NAME, SearchCondition.EQUAL, name);
                qs.appendAnd();
                qs.appendWhere(searchCondi, new int[] { 0 });
            }
            
            
            // Sorted by modifying time in descending order.
            OrderBy orderby = new OrderBy(new ClassAttribute(WTDocument.class, "thePersistInfo.modifyStamp"), true);
            qs.appendOrderBy(orderby, new int[] { indexWTDocument });
            LOGGER.debug(">>>>> queryWTDocument(): qs=" + qs);
            QueryResult qr = PersistenceHelper.manager.find((StatementSpec) qs);
            LOGGER.debug(">>>>> queryWTDocument(): qr=" + qr);
            if (qr != null) {
                ObjectVector vector = new ObjectVector();
                while (qr.hasMoreElements()) {
                    Object obj = qr.nextElement();
                    if (obj instanceof Persistable[]) {
                        Persistable[] apersist = (Persistable[]) obj;
                        vector.addElement(apersist[0]);
                    } else {
                        vector.addElement(obj);
                    }
                }
                if (!vector.isEmpty()) {
                    qr = new QueryResult(vector);
                }
                qr = (new LatestConfigSpec()).process(qr);
            }
            if (qr != null) {
                while (qr.hasMoreElements()) {
                    result = (WTDocument) qr.nextElement();
                }
            }
            
            return result;
        } catch (Exception e) {
            String errorMsg = MessageFormat
                    .format(">>>>> Failed to get WTDocument objects with the given parameters: name-[{0}], softTypes-[{1}].",
                            name, softTypes);
            LOGGER.error(">>>>>" + errorMsg, e);
            throw new WTException(e, errorMsg);
        }
        
        
        
        
        
    }
    

}
